package com.uzai.console.web.mini;

import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.uzai.console.common.utils.WXXmlToMapUtil;
import com.uzai.console.common.utils.signature.MsgCrypt;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.service.mini.DeviceMiniInfoService;
import com.uzai.console.web.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author lucher
 * @date 2019-06-17 11:39
 */
@Api(value = "小程序回调函数",tags = "小程序|小程序回调函数", hidden = true)
@ApiSort(9)
@RestController
public class MiniCallbackController extends BaseController {

    private static Logger logger = LoggerFactory.getLogger(MiniCallbackController.class);

    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;
    @Autowired
    private DeviceMiniInfoService deviceMiniInfoService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 复用公众号快速注册小程序回调获取授权
     * @param status 自定义参数merId_appid
     * @param ticket 公众号扫码授权的凭证
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "复用公众号快速注册小程序回调函数", hidden = true)
    @GetMapping("/mini/fastregister/callback")
    public void fastregisterCallback(String status, String ticket) throws Exception {
        logger.info("--fastregister-callback-status:{},ticket:{}",new Object[]{status, ticket});
        try{
            //复用公众号快速创建小程序
            deviceMiniInfoService.fastregisterCallback(status, ticket);

            getResponse().sendRedirect(uzaiConsoleSysConfig.getTokenAuthReturnUrl() + "?state=1");

        }catch(Exception e){
            logger.error("callback err:{}",e);
            getResponse().sendRedirect(uzaiConsoleSysConfig.getTokenAuthReturnUrl() + "?state=0&msg="+ URLEncoder.encode(e.getMessage(),"UTF-8"));
        }
    }

    /**
     * 第三方平台对小程序或者公众号授权回调函数
     * @param status 自定义参数merId_authtype（1-公众号；2-小程序）
     * @param auth_code 授权码
     * @param expires_in 到期时间秒数
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "第三方平台对小程序或者公众号授权回调函数", hidden = true)
    @GetMapping("/mini/auth/callback")
    public void authCallback(String status, String auth_code, Integer expires_in) throws Exception {
        logger.info("--auth-callback-ticket:status:{},auth_code:{},expires_in:{}",new Object[]{status,auth_code, expires_in});
        try{
            //调用授权回调函数
            deviceMiniInfoService.authCallback(status, auth_code, expires_in);

            getResponse().sendRedirect(uzaiConsoleSysConfig.getTokenAuthReturnUrl() + "?state=1");

        }catch(Exception e){
            logger.error("callback err:{}",e);
            getResponse().sendRedirect(uzaiConsoleSysConfig.getTokenAuthReturnUrl() + "?state=0&msg="+ URLEncoder.encode(e.getMessage(),"UTF-8"));
        }
    }

    /**
     * 接收第三方平台推送ticket回调函数
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "接收第三方平台推送ticket回调函数", hidden = true)
    @RequestMapping(value = "/mini/checkticket/callback")
    public Object access(HttpServletRequest request, HttpServletResponse response) throws IOException {
        logger.info("/mini/checkticket/callback invok success.");
        String postData = getPostData(request);

        logger.info("postData : {} ", postData);
        Map<String, String> postDataMap;
        Map<String, String> decryptMap;
        try {
            postDataMap = WXXmlToMapUtil.xmlToMap(postData);

            String encrypt = postDataMap.get("Encrypt");
            // 通过appid查询三方配置信息
            String component_appid = postDataMap.get("AppId");
            String aesKey = uzaiConsoleSysConfig.getMiniComponentAesKey();

            //通过appid查询对应三方平台配置
            String decrypt = MsgCrypt.decrypt(component_appid, aesKey, encrypt);

            decryptMap = WXXmlToMapUtil.xmlToMap(decrypt);
            logger.info("decrypt : {}", JSONObject.toJSONString(decrypt));
            String verifyTicket = decryptMap.get("ComponentVerifyTicket");
            if (StringUtils.isNotBlank(verifyTicket)) {
                logger.info("component_verify_ticket: {}", verifyTicket);

                String key = "component_verify_ticket_" + component_appid;

                redisTemplate.opsForValue().set(key, verifyTicket, 40000L, TimeUnit.SECONDS);
            } else {
                logger.info(" ticket blank ------");
            }

            //
        } catch (Exception e) {
            logger.error(" xml to map err :  {} , cause : {}", e.getMessage() , e.getCause());
        }

        response.setCharacterEncoding("UTF-8");
        try {
//            logger.info("component_verify_ticket:" + request.getParameter("component_verify_ticket"));
            ServletOutputStream out = response.getOutputStream();
            out.print("success");
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static String getPostData(HttpServletRequest request) {
        StringBuffer data = new StringBuffer();
        String line = null;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            while (null != (line = reader.readLine()))
                data.append(line);
        } catch (IOException e) {
        } finally {
        }
        return data.toString();
    }

}
